package cn.caplike.demo.spring.bean.lifecycle.service.impl;

import cn.caplike.demo.spring.bean.lifecycle.service.AccountService;
import cn.caplike.demo.spring.dao.AccountDao;
import cn.caplike.demo.spring.domain.Account;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

@Service("accountService")
// @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class AccountServiceImpl implements AccountService {

    private final InnerClass innerClass = new InnerClass();
    @Resource
    private AccountDao dao;

    @Override
    @Transactional
    public void doTransactionalOp() {
        final Account account = dao.findAccountByName("LiKe");
        account.setMoney(BigDecimal.ZERO);
        dao.updateAccount(account);
        this.anotherTransactionOp(account);

        // send
    }

    /**
     * 如果当前方法是以非事务的方式运行, 那在改方法中出现异常不会导致数据回滚
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void anotherTransactionOp(Account account) {
        account.setMoney(BigDecimal.TEN.multiply(BigDecimal.TEN));
        dao.updateAccount(account);
        int i = 1 / 0;
        // innerClass.innerTransactionOp(account);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void transfer(String sourceName, String targetName, BigDecimal money) {
        System.out.println("transfer....");
        //2.1根据名称查询转出账户
        Account source = dao.findAccountByName(sourceName);
        //2.2根据名称查询转入账户
        Account target = dao.findAccountByName(targetName);
        //2.3转出账户减钱
        source.setMoney(source.getMoney().subtract(money));
        //2.4转入账户加钱
        target.setMoney(target.getMoney().add(money));
        //2.5更新转出账户
        dao.updateAccount(source);

        int i = 1 / 0;

        //2.6更新转入账户
        dao.updateAccount(target);
    }

    // -----------------------------------------------------------------------------------------------------------------

    private final class InnerClass {
        private void innerTransactionOp(Account account) {
            account.setMoney(BigDecimal.valueOf(20.78));
            dao.updateAccount(account);
        }
    }
}
